use crate::error::Error;
use crate::{controller, node_watch};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use wanmesh_server::http::client::rpc;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerConfig {
    #[serde(flatten)]
    pub inner: rpc::Setting,
    pub auth: ServerAuthConfig,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerAuthConfig {
    pub username: String,
    pub password: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
    pub node_id: String,
    pub server: ServerConfig,
    pub log: wanmesh_common::log::Config,
}

pub struct App {
    config: Config,
}

impl App {
    pub fn new(config: Config) -> Self {
        Self { config }
    }

    pub async fn run(&self) -> Result<(), Error> {
        let log_setting = wanmesh_common::log::Setting::try_from(&self.config.log)?;
        wanmesh_common::log::init(log_setting);

        let node_id = self.config.node_id.clone();

        let api_client_auth = Arc::new(wanmesh_server::http::client::Auth::new());

        let api_client = Arc::new(wanmesh_server::http::client::Client::new(
            self.config.server.inner.clone(),
            api_client_auth.clone(),
        ));

        let server_auth = ServerAuth::new(
            self.config.server.auth.clone(),
            api_client.clone(),
            api_client_auth,
        );

        let endpoint_controller = Arc::new(controller::EndpointController::new(
            node_id.clone(),
            api_client.clone(),
        ));

        endpoint_controller.sync_all().await?;

        let server_auth_task_handle = tokio::spawn(async move {
            if let Err(e) = server_auth.keep_auth().await {
                log::error!("登录授权异常结束: {:?}", e);
            }
        });

        let node_watch_task = api_client
            .node
            .watch(
                node_id.as_str(),
                node_watch::MessageHandler::new(endpoint_controller.clone()),
            )
            .await?;

        let node_endpoint_watch_task_handle = tokio::spawn(async move {
            node_watch_task.run().await;
        });

        tokio::select! {
            _ = server_auth_task_handle => {},
            _ = node_endpoint_watch_task_handle => {},
        };

        log::error!("应用异常结束");
        Ok(())
    }
}

struct ServerAuth {
    auth_config: ServerAuthConfig,
    api_client: Arc<wanmesh_server::http::client::Client>,
    api_client_auth: Arc<wanmesh_server::http::client::Auth>,
}

impl ServerAuth {
    fn new(
        auth_config: ServerAuthConfig,
        api_client: Arc<wanmesh_server::http::client::Client>,
        api_client_auth: Arc<wanmesh_server::http::client::Auth>,
    ) -> Self {
        Self {
            auth_config,
            api_client,
            api_client_auth,
        }
    }

    async fn keep_auth(&self) -> Result<(), Error> {
        let mut token = self
            .api_client
            .auth
            .login(
                self.auth_config.username.as_str(),
                self.auth_config.password.as_str(),
            )
            .await?;
        loop {
            self.api_client_auth
                .set_access_token(token.access_token.clone())
                .await;

            tokio::time::sleep(std::time::Duration::from_secs(token.expires_in / 2)).await;

            token = self
                .api_client
                .auth
                .refresh_token(&wanmesh_server::dto::auth::RefreshTokenRequest {
                    refresh_token: token.refresh_token,
                })
                .await?;
        }
    }
}
